Site A.T.L.A.N.T.I.C-83
COURS = Comprendre son ordinateur (Chapitre_2) - VERSION: 1.0 (M.A.J: 15/03/10)
- AUTEUR(s): Bernard GIACOMONI
Ecran large mobile
Retour
sommaire cours

II.PRINCIPES FONCTIONNELS DES ORDINATEURS ET DE LA PROGRAMMATION INFORMATIQUE

II.1.OBJECTIFS ET PLAN DU CHAPITRE:


Ce premier chapitre vise à définir ou préciser (suivant votre niveau de connaîssance) certains concepts généraux concernant le fonctionnement interne et la programmation des ordinateurs. Bien que ces concepts ne soient pas d'une grande complexité, certains d'entre eux vous paraîtront peut-être un peu théoriques et éloignés de vos attentes. Il est cependant nécessaire que vous puissiez les identifier précisément, car ce sont eux qui justifient les solutions techniques adoptées par les constructeurs de matériels et les développeurs de logiciels.
Dans un premier temps, nous allons étudier rapidement le modèle de VON NEUMAN, sur lequel sont basés la presque totalité des processeurs informatiques du marché. Cette étude va nous permettre d'aborder les principaux concepts architecturaux des systèmes informatiques. Nous aborderons ensuite la notion de programme. Cette étude nous permettra de définir et préciser les concepts de base de la programmation informatique.


II.2.LA MACHINE DE VON NEUMAN ET SES EVOLUTIONS:


II.2.1.DESCRIPTION GENERALE:

La plupart des ordinateurs proposés actuellement sur le marché sont basés sur un modèle proposé par le mathématicien américain JOHN VON NEUMANN au début des années 1950. Ce modèle, habituellement nommé «MACHINE DE VON NEUMAN», est en fait, pûrement théorique. Il fait intervenir les entités logiques suivantes:
Un EXECUTEUR (ou PROCESSEUR), capable de réaliser des OPERATIONS suivant les INSTRUCTIONS contenues dans une MEMOIRE. Les opérations, en s'exécutant, peuvent utiliser et engendrer des DONNEES, lesquelle peuvent être également stockées dans cette mémoire.
Bien qu'il existe (ou qu'il ait existé) des ordinateurs fonctionnant suivant des modèles différents, ceux-ci sont restés cantonnés à des domaines très restreints ou expérimentaux.
Les processeurs actuels basés sur ce modèle sont tous munis de mécanismes additionnels qui n'étaient pas explicitement prévus par lui, mais qui se sont petit à petit imposés auprès des utilisateurs. Ce qui suit décrit donc le modèle de Von Neuman «enrichi» de ces additions.


II.2.2.SCHEMA DE PRINCIPE:

Modèle de Von Neuman

II.2.3.ANALYSE DU SCHEMA DE PRINCIPE:

II.2.3.1.NOTION D'OPERATION:

Une OPÉRATION (appelée encore PRIMITIVE) est une action élémentaire que peut réaliser le PROCESSEUR (par exemple: une addition, une comparaison, etc.). L'ensemble des types d'opérations qu'un exécuteur est capable de réaliser est appelé CODE D'ORDRE de cet exécuteur.
Dans le modèle de Von Neuman, chaque instruction fait référence à une opération. En réalité, il existe des processeurs pour lesquels une instruction peut provoquer l'exécution de plusieurs opérations (processeurs à microprogrammes).

II.2.3.2.INSTRUCTIONS ET DONNEES:

Les opérations du code d'ordre utilisent des DONNEES que la machine met à leur disposition, afin d'engendrer d'autres données (par exemple, l'opération addition va utiliser deux données X et Y afin de calculer leur somme et de placer le résultat dans la donnée Z ).
Une INSTRUCTION doit donc spécifier non seulement une ou des opérations à exécuter, mais aussi la manière d'accéder aux données utilisées par ces opérations (OPERANDES) et la destination des données produites (qu'en faire? les ranger dans l'accumulateur ou en mémoire? les communiquer à l'U.E.S ? etc.).
L'ensemble des instructions exécutables par un processeur constitue son LANGAGE INTERNE (encore appelé LANGAGE MACHINE).

II.2.3.3.LA MEMOIRE CENTRALE:

Le modèle de Von Neuman suppose que les instructions et les données que celles-ci utilisent ou produisent soient enregistrées dans un même dispositif appelé MEMOIRE CENTRALE de la machine. Celle-ci est formée d'un certain nombre de CASES dans lesquelles l'exécuteur peut lire ou écrire. Une case mémoire peut ainsi contenir soit l'enregistrement d'une instruction (et d'une seule), soit celui d'une donnée (et d'une seule).
Les cases mémoires sont numérotées de 1 en 1, à partir de 0. Le numéro d'ordre d'une case est son ADRESSE MEMOIRE. Du fait de l'existance de l'adresse 0, une mémoire dont la plus haute adresse est N contient N+1 cases.

II.2.3.4.L'EXECUTEUR:

Le modèle de VON NEUMAN distingue dans l'EXECUTEUR trois entités fonctionnelles:
L'UNITE DE CONTRÔLE (U.C):
Elle contrôle l'exécution des instructions: Elle lit les instructions en mémoire, les décode et en déduit la (ou les) opération(s) à exécuter, puis elle communique cette (ou ces) opération(s) à l'unité de traitement. Le COMPTEUR ORDINAL est une sous-entité de l'U.C. chargée de mémoriser l'adresse de l'instruction en cours d'exécution.
L'U.C. incrémente son contenu d'une unité après l'exécution de chaque instruction. De ce fait, en l'absence de toute autre cause, les instructions sont exécutées «en séquence», c'est à dire dans l'ordre des adresses croissantes (après exécution de l'instruction contenue la case 100, on tente d'exécuter l'instruction contenue dans la case 101, et ainsi de suite).
L'UNITE DE TRAITEMENT (U.T):
Elle reconnaît le code d'ordre des opérations présentées par l'U.C. ainsi que les opérandes, acquier en mémoire ou à partir de l'U.E.S les valeurs de ces opérandes, exécute les opérations, puis renvoie les résultats d'exécution vers la mémoire ou vers l'U.E.S afin de les mettre à disposition de la périphérie.
L'U.T peut également modifier la valeur du compteur ordinal, changeant par là même la séquence d'exécution des instructions. Cette modification peut résulter soit de l'exécution de types d'opérations particuliers (opérations de RUPTURE DE SEQUENCE), soit de la détection d'un événement lié au fonctionnement interne (anomalies de fonctionnement, par exemple). Ce type de fonctionnement est appelé INTERRUPTION INTERNE.
L'ACCUMULATEUR est une sous entité qui permet de mémoriser temporairement une donnée en attente d'un traitement: donnée acquise par l'unité d'entrée-sortie ou lue dans la mémoire ou résultat de calcul intermédiaire. Elle permet ainsi d'éviter des stockages-destockages en mémoire de données transitoires. Les processeurs actuels possèdent en général plusieurs accumulateurs.
L'UNITE D'ENTREE-SORTIE (U.E.S):
Elle est chargée de la prise en compte des données et signaux en provenance de la périphérie et de l'envoi de données vers cette périphérie.
Le contenu du compteur ordinal peut être modifié par l'U.E.S. Ceci permet de prendre en compte certains événements liés à la périphérie (arrivée d'un message, signal horaire, etc.) en déroutant la séquence d'exécution vers des traitements spécifiques. Après exécution de ces traitements, la première séquence peut être reprise au point où elle a été interrompue. Ce mécanisme est appelé "INTERRUPTION EXTERNE".
REMARQUE:
Les entités telles que le compteur ordinal ou l'accumulateur sont en fait des mémoires intégrées à l'exécuteur. On les appelle des REGISTRES. En théorie, deux registres suffisent pour le modèle de Von Neuman. Cependant, Les processeurs actuels possèdent de nombreux registres (plusieurs accumulateurs, compteur ordinal, registre d'état, registre d'instruction, etc. ).

II.2.4.REMARQUES:

Cette étude globale permet déja d'entrevoir l'origine de certains comportements caractéristiques des ordinateurs, que l'on qualifie souvent du terme générique de "plantages":
  • Le fait que la mémoire centrale soit commune aux instructions et aux données entraîne la possibilité qu'un programme se modifie lui-même: En effet, rien n'empêche une instruction d'un programme d'en modifier une autre (ou même de se modifier elle-même). En fait, cette possibilité est rarement utilisée par les programmeurs. En revanche, la modification peut résulter d'une erreur de programmation (erreur d'adresse de rangement d'un résultat). C'est tout de même une erreur assez grossière qui ne se rencontre que dans des logiciels en cours de mise au point et provoque en général des dysfonctionnements immédiats et caractérisés (affichage de messages du type "instruction illégale").
  • Par le même mécanisme, un programme peut modifier un autre programme. dans ce cas, le "plantage" peut ne pas être immédiat, si le programme modifié ne s'exécute pas tout de suite. Ce genre de dysfonctionnement est donc beaucoup plus délicat à diagnostiquer.
  • Toujours par le même mécanisme, l'U.C. peut lire une donnée à la place d'une instruction: il suffit pour cela que le compteur ordinal soit chargé avec l'adresse d'une donnée (au lieu d'une instruction). Ce type de dyfonctionnement, qui provoque également l'affichage de messages du type "instruction illégale" peut se rencontrer même dans des applications très au point, car si son origine peut être un défaut du logiciel (mauvaise adresse de rupture de séquence, par exemple), elle peut être aussi matérielle: survenue d'une interruption non prévue, provoquée par l'ajout d'un nouveau matériel, mauvais chargement d'un programme en mémoire (erreur lecture disque), etc.


II.3.PROGRAMMES ET PROGRAMMATION:

II.3.1.NOTION D'ALGORITHME:

II.3.1.1.DEFINITION:

Un ALGORITHME représente l'énoncé d'une procédure de résolution opérationnelle d'un problème donné, écrit dans un langage compréhensible pour l'EXECUTANT (ou EXECUTEUR) qui est chargé de la mettre en oeuvre.
Un algorithme se présente sous la forme d'une suite finie de directives. Un algorithme est valide s'il est capable de résoudre le problème pour lequel il a été créé en exécutant un nombre fini de directives.


EXEMPLES:
  • On nomme «algorithme de la division» la procédure décrivant pas à pas la méthode de réalisation d'une division de deux nombres (ne pas confondre avec la «théorie de la division», qui justifie cette méthode).
  • Une recette de cuisine peut être assimilée à un algorithme décrivant une procédure de préparation d'un plat.

II.3.1.2.CARACTERISTIQUES PRINCIPALES:

LES DIRECTIVES:
Il est possible de classer les directives d'un langage algorithmique en trois catégories: les directives séquencielles, les alternatives et les répétitives.


DIRECTIVES SEQUENCIELLES:
La plupart des directives spécifient une ou des opérations à effectuer impérativement et doivent être exécutées dans l'ordre ou elles sont énoncées:

EXEMPLE:
  • Placer 300 g de farine dans un saladier
  • Mélanger avec 3 cuillerées d'huile d'olives
  • Ajouter 100 grammes d'eau
  • etc...


DIRECTIVES ALTERNATIVES:
Cependant, il peut également exister des directives qui subordonnent la suite des directives à exécuter à la réalisation d'une condition:

EXEMPLE: SI ma destination se trouve dans la ville ALORS je prends mon scooter SINON je prends mon automobile.


DIRECTIVES REPETITIVES:
Les directives répétitives permettent de répéter une séquence de directives jusqu'à ce qu'un condition soit remplie.

EXEMPLE:
  • TANT QUE je n'ai pas tiré un double six FAIRE: Je relance les dés FINFAIRE
  • POUR tous les nombres de 0 à 100 FAIRE:
    je calcule leur racine carrée
    j'ajoute tous les résultats
  • FINFAIRE
LES DONNEES:
Les directives d'un algorithme agissent sur un certain nombre de DONNEES: dans les exemples ci-dessus, «farine» ou «destination» sont des données. L'ensemble des données qu'un algorithme utilise, crée ou modifie constitue l'ESPACE D'EXECUTION» de cet algorithme.
Dans un algorithme, chaque donnée doit être DECLAREE. Cette opération consiste à lui attribuer un TYPE (Type numérique, logique, textuel, tableau de données, etc.). La déclaration d'une donnée s'écrit souvent comme suit:
EXEMPLE (déclaration de la donnée PRIX_DE_REVIENT):
var PRIX_DE_REVIENT en NUMERIQUE
REMARQUE:
Les langages algorithmiques sont, par principe, très proches des langages «humains». Cependant, il existe certaines conventions d'écriture, qui se traduisent par des mots clefs (les SI, ALORS, SINON, TANT QUE, FINFAIRE, etc.. utilisés dans les exemples), le typage des données et des manières de disposer les directives (indentation).

II.3.2.NOTION DE PROGRAMME:

II.3.2.1.DEFINITION:

En informatique, un PROGRAMME n'est autre que la traduction d'un algorithme dans un langage opérationnel pouvant être exécuté par un ordinateur (LANGAGE DE PROGRAMMATION).
De ce fait, un programme se présente sous la forme d'une suite finie d'instructions, agissant sur un ensemble fini de données. Un programme est valide s'il est capable de résoudre le problème pour lequel il a été créé en exécutant un nombre fini d'instructions.

II.3.2.2.REPRESENTATION D'UN PROGRAMME EN MEMOIRE

Pour qu'un programme puisse être exécuté directement par un PROCESSEUR tel que nous l'avons décrit plus haut, il doit être écrit dans le LANGAGE INTERNE de ce processeur. Sinon, il faudra passer par une phase de traduction automatique du programme en langage interne, que l'on appelle COMPILATION ou INTERPRETATION, suivant la manière dont elle est réalisée.
Il faudra d'autre part charger ce programme en mémoire. Lors de son exécution, un programme occupera donc un ensemble de cases de la mémoire centrale, certaines étant allouées à ses instructions et d'autres à ses données.

II.3.2.3.STRUCTURE D'UNE INSTRUCTION

Chaque type de processeur informatique possède un langage interne qui lui est propre, bien que les processeurs appartenant à une même gamme (pentium, celeron, athlon...) aient des jeux d'instruction très semblables. Cependant, on peut distinguer quelques caractéristiques communes à tous les langages internes.
Ainsi, l'enregistrement représentant une instruction en langage interne est toujours composé de trois champs de données distincts:


CODE D'ORDREMODE D'ADRESSAGEOPERANDE(S)


CODE D'ORDRE:
C'est un code numérique (un nombre entier positif) permettant d'identifier le type d'opération (addition, soustraction, lecture ou écriture en mémoire, etc.).


MODE D'ADRESSAGE:
Il s'agit également d'un identificateur permettant de déterminer le «mode d'adressage des opérandes». Nous verrons plus loin ce que recouvre ce concept.


OPERANDES:
Ce champ, combiné au champ précédent, permet d'accéder à la valeur courante de chacun des opérandes utilisés par l'operation. Selon le type d'instruction, il peut représenter un seul opérande (cas le plus fréquent) ou être divisé en plusieurs sous-champs, chacun représentant un opérande. Un champ d'opérande contient toujours un nombre entier. Ce nombre peut représenter directement la valeur de l'opérande (instruction à opérande immédiat). Il peut également représenter une adresse mémoire (il est alors positif ou nul). Dans ce dernier cas, suivant le mode d'adressage, ce nombre peut représenter:
  • L'adresse mémoire de l'opérande (adressage direct).
  • L'adresse de l'adresse mémoire de l'opérande (adressage indirect).
  • L'adresse de début d'un tableau de données dans lequel se trouve l'opérande. Pour trouver l'adresse de l'opérande, l'unité de traitement ajoutera à l'adresse de début le contenu d'un registre contenant la valeur d'un nombre entier positif appelé index (adressage indexé – le registre est appelé REGISTRE D'INDEX).
  • Ces modes peuvent se combiner entre eux.


EXEMPLE:
Soit une instruction permettant de lire une donnée en mémoire et de la placer dans l'accumulateur. Représentons par LMA ( Load Memory to Accumulator) son code d'ordre. Supposons que cette instruction n'ait qu'un seul opérande, dont la valeur est le nombre 1000.
Supposons également:
  • Que le registre d'index contient la valeur 5.
  • Que la case mémoire d'adresse 1000 contient la valeur 1001.
  • Que la case mémoire d'adresse 1001 contient la valeur -2.
  • Que la case mémoire d'adresse 1005 contient la valeur 24.
Suivant le contenu du champ MODE D'ADRESSAGE, le contenu de l'accumulateur en fin d'exécution sera:


TYPE D'OPERANDE CONTENU DE L'ACCUMULATEUR COMMENTAIRE
Opérande Immédiat 1000 C'est la valeur immédiate de l'opérande
Adressage direct 1001 La valeur 1000 de l'opérande est interprétée comme l'adresse de l'opérande. La case 1000 contenant 1001, c'est cette valeur qui sera chargée dans l'accumulateur.
Adressage indirect -2 La valeur 1000 de l'opérande est interprétée comme l'adresse d'une case dans laquelle on trouvera l'adresse réelle de l'opérande. La case 1000 contenant 1001, on ira chercher la valeur contenue dans la case 1001, c'est à dire -2.
Adressage indexé 24 La valeur 1000 de l'opérande est interprétée comme étant l'adresse d'un tableau de valeurs, dans lequel le rang de l'opérande est indiqué par le contenu du registre d'index. Ce contenu étant 5, c'est le contenu de la case 1005 (1000+5) qui sera chargé dans l'accumulateur, c'est à dire 24.


MEME CHOSE SOUS FORME DE SCHEMA:


Modes d'adressage


II.3.3.INSTRUCTIONS DES LANGAGES INTERNES:

II.3.3.1.INSTRUCTIONS SEQUENCIELLES:

Ce sont des instructions qui ne modifient pas l'ordre d'exécution séquenciel du programme (si l'instruction est placée dans la case N, la prochaine instruction sera celle de la case N+1). Elles correspondent donc aux directives séquencielles des algorithmes). On trouve essentiellement:
  • Des instructions permettant de lire la mémoire et de charger le contenu dans un registre (accumulateur, registre d'index, registre d'entrée-sortie, etc.).
  • Des instructions permettant de lire un registre et de charger son contenu en mémoire.
  • Des instruction lisant un registre et chargeant son contenu dans un autre registre.
  • Des instructions déclenchant les entrées-sorties de données (envoi du contenu du registre d'entrée-sortie vers la périphérie ou l'inverse).
  • Des instructions de calcul numérique (exemple: addition de l'accumulateur avec la mémoire, résultat dans l'accumulateur).
  • Etc.

II.3.3.2.INSTRUCTIONS INTERROMPANT LA SEQUENCE D'EXECUTION:

Ces instructions sont capables de modifier la séquence d'instructions en aiguillant l'exécution vers une adresse quelconque, différente de l'adresse suivante. L'opération revient à modifier le contenu du COMPTEUR ORDINAL en chargeant dans celui-ci la valeur d'un opérande. Cette rupture de séquence peut être:
INCONDITIONNELLE:
L'exécution de l'instruction de rupture modifie toujours la valeur du compteur ordinal. Ce type d'instruction n'existe pas dans un langage algorithmique, car les directives d'un algorithme n'ont pas d'adresse. Elle correspondrait à une directive du type: CONTINUER L'EXECUTION à l'adresse N
CONDITIONNELLE:
La modification du compteur ordinal est subordonnée à la réalisation d'une condition au moment de son exécution (une condition sur la valeur d'un registre, par exemple). Si la condition est réalisée, l'exécutant est dérouté vers l'adresse spécifiée par l'instruction. Sinon, l'exécutant continue en séquence. Ce type d'instruction correspond à une directive de langage algorithmique libellée comme suit: SI La condition C est réalisée ALORS continuer l'exécution à l'adresse N SINON continuer en séquence.
REMARQUE:
Les langages internes ne possèdent pas d'instructions répétitives. Pour répéter un traitement, il faut donc utiliser une combinaison de ruptures de séquences conditionnelles et inconditionnelles, du type:
ADRESSESINSTRUCTIONS
A1SI la condition C est réalisée ALORS continuer l'exécution à l'adresse A2
A1+1Instructions séquencielles pouvant modifier la condition C
(sinon, on ne sortirait jamais de la boucle !)
etc...
A2-1CONTINUER L'EXECUTION à l'adresse A1 (rebouclage sur A1)
A2Suite du programme...
COMMENTAIRES:
  • L'instruction contenue par l'adresse A1 est une instruction conditionnelle. Donc, si la condition C n'est pas réalisée, l'exécution se continue en séquence, c'est à dire en A1+1.
  • Les cases de A1+1 à A2-2 contiennent des traitements susceptibles de réaliser la condition C.
  • On arrive ensuite à l'adresse A2-1, qui contient une instruction de rupture de séquence inconditionnelle vers l'adresse A1. L'exécution est donc déroutée (rebouclée) vers cette adresse.
  • L'instruction contenue par l'adresse A1 est donc réexécutée. Si les instructions de A1+1 à A2-2 n'ont pas réalisé la condition C, on continue en A1+1 comme la première fois, et on reboucle en A1.
  • On ne sortira de la boucle que quand C sera réalisée, auquel cas l'instruction contenue par l'adresse A1 déroutera l'exécution en A2, c'est à dire après la rupture inconditionnelle, provoquant la fin du rebouclage.

II.3.3.3.AUTRES CAS DE RUPTURE DE SEQUENCE:

La séquence d'exécution peut également être provoquée par la survenue d'un événement ou la détection d'une anomalie de fonctionnement. Dans ce cas, c'est l'unité d'entrée-sortie ou l'unité de traitement qui modifient le compteur ordinal. L'opération permet de transférer l'exécution vers l'adresse de début d'un programme de traitement de cet événement ou de cette anomalie (gestionnaire d'événement). Un tel déroutement s'appelle INTERRUPTION PRIORITAIRE. L'adresse chargée dans le compteur ordinal s'appelle: ADRESSE D'INTERRUPTION.

II.3.4.UN PETIT EXEMPLE DE PROGRAMME:

Soit une machine dont le langage interne supporte les instructions suivantes (les codes d'ordre son représentés par des noms LMA, LAM, etc...):


CODE D'ORDREOPERATION REALISEE
LMACharger le contenu de la mémoire dans l'accumulateur.
LAMCharger le contenu de l'accumulateur dans la mémoire.
LIACharger la valeur de l'opérande dans l'accumulateur.
LAESCharger la valeur de l'accumulateur dans le registre d'entrée-sortie.
MMAMultiplier le contenu de la mémoire avec le contenu de l'accumulateur, résultat dans l'accumulateur.
ADAAdditionner la valeur de l'operande à l'accumulateur, resultat dans l'accumulateur.
SMASoustraire le contenu de la mémoire au contenu de l'accumulateur, résultat dans l'accumulateur.
JANSi l'accumulateur contient une valeur négative, charger la valeur de l'opérande dans le compteur ordinal.
GOSUBEcrire le contenu du registre d'entrée-sortie sur un peripherique.


Supposons que nous voulions déterminer le plus petit nombre entier dont le carré est supérieur à 100. Le programme en mémoire ressemblerait à ce qui suit (les adresses mémoires sont choisies arbitrairement et le mode d'indexation est représenté par deux lettres: im pour immédiat, di pour direct):


ADRESSE MEMOIRECODE D'ORDREMODE D'ADESSAGEVALEUR DE L'OPERANDEACTION
1000LIAim100100 --> accumulateur
1001LAMdi1013Accumulateur --> case 1013 (la case 1013 contient maintenant la valeur 100)
1002LIAim00 --> accumulateur
1003LAMdi1012Accumulateur --> case 1012 (la case 1012 va contenir les valeurs successives des entiers)
1004LMAdi1012Contenu case 1012 --> accumulateur
1005ADAIm1Contenu accumulateur + 1 --> accumulateur
1006MMAdi1012Contenu case 1012 * Contenu accumulateur --> Accumulateur
1007SMAdi1013Contenu accumulateur – 100 --> accumulateur
1008JANIm1004Si la valeur de l'accumulateur est devenue négative, renvoyer l'exécution à la case 1004
1009LMAdi1012Contenu case 1013 --> Accumulateur
1010LAESSans objetSans objetContenu accumulateur --> registre d'entrée-sortie
1011GOSUBSans objetId. de l'écranEmettre le contenu du registre d'entrée-sortie vers l'ecran


La logique de ce fragment de programme peut être décrite par le logigramme suivant:


Logigramme


II.3.5.LES LANGAGES EVOLUES:

II.3.5.1.CARACTERISTIQUES DES LANGAGES EVOLUES:

Ces types de langages se rapprochent beaucoup par leur forme des langages algorithmiques, tout en obeissant à des rêgles syntaxiques et sémantiques rigoureuses. Ils diffèrent essentiellement des langages internes par le fait que les opérations et les données sont représentées par des symbôles littéraux. Par exemple:
  • Un type d'opération est représenté par un MOT-CLEF ou un OPERATEUR littéral alors que dans un langage interne, il est représenté directement par son identifiant dans le code d'ordre d'un type de processeur donné (ce qui le rend dépendant de ce type de processeur).
  • Une donnée est représentée par un NOM, encore appelé ETIQUETTE (alors que dans un langage interne, une donnée est représentée par un NOMBRE, qui est soit sa valeur soit son adresse en mémoire). Dans un langage évolué, une donnée ressemble donc à une VARIABLE ou une CONSTANTE (aux sens mathématiques de ces termes), indépendante de toute implantation en mémoire.
EXEMPLES:
En langage C, une addition s'écrit:
C = A + B;
(A, B et C sont des étiquettes de données , = et + sont des opérateurs littéraux.)

En langage C également, une instruction de rupture conditionnelle s'écrira:
if ( Temperature>0) { Etat = ''Liquide'' } else { Etat = ''Glace'' }
(Temperature et Etat sont des données, ''Liquide » et « Glace » sont des constantes littérales,
if, then, else et endif sont des mots-clefs, > est un opérateur de comparaison).

Les codes objets ainsi écrits ont l'avantage de faire abstraction du type de processeur et de l'implantation en mémoire du programme. Cependant, ils ne sont pas exécutables par un processeur. Pour obtenir un programme exécutable, il faut (au minimum) attribuer à chaque étiquette une adresse mémoire et remplacer chaque directive de langage évolué par une séquence d'instructions en langage machine équivalente. Ce type de traduction est effectué automatiquement par des logiciels appelés soit COMPILATEURS/EDITEURS DE LIENS, soit INTERPRETEURS:
  • Les COMPILATEURS/EDITEURS DE LIENS traduisent les langages évolués dans un langage intermédiaire proche du langage interne de la machine, mais qui représente toujours les adresses sous forme de symboles (LANGAGES INTERNES TRANSLATABLES). D'autres logiciels, appelés CHARGEURS remplacent ces adresses symboliques par des adresses réelles au moment du chargement du programme en mémoire. Les langages évolués compilés les plus courants sont les langages C et C++, ADA, Fortran, etc.
  • Les INTERPRETEURS interprètent chaque directive de langage évolué par le lancement de l'exécution d'un programme en langage interne équivalent. Il n'y a donc pas d'étape intermédiaire (de ce fait, l'interprétation d'un code est toujours plus lente que son exécution après compilation). Les langages évolués interprétés les plus courants sont Java, Javascript, PHP, etc.
  • Pour un langage évolué donné, il peut exister à la fois un compilateur et un interpréteur.

II.3.5.2.UTILITE DES LANGAGES EVOLUES:

Un programme directement réalisé en langage interne présente les défauts suivants:
  • Il ne peut fonctionner que sur un seul type de processeur, doté du code d'ordre utilisé pour écrire le programme. Pour le «porter» sur une machine de type différent, il faut donc le réécrire totalement: il serait évidemment très ennuyeux d'avoir à réécrire Internet Explorer ou Word pour tous les types de processeurs existants!
  • Il ne peut être chargé qu'à partir d'une adresse déterminée de la mémoire. Il est donc difficile de le faire cohabiter avec d'autres programmes.
  • Le code objet est très peu lisible, ce qui rend la mise au point et la reprise par d'autres développeurs difficiles.
  • Il est très difficile à modifier, car trop lié aux environnements matériel et d'utilisation.

A l'inverse, un programme en langage évolué est:
  • Indépendant de tout type de processeur (pour l'adapter à un processeur, il suffit de choisir le compilateur ou l'interpréteur qui convient).
  • Indépendant de l'implantation mémoire (il peut être chargé dans n'importe quelle zone de mémoire libre).
  • Très lisible et facilement modifiable.

De ce fait, les développeurs n'utilisent pratiquement jamais directement le langage interne. En général, ils programment dans des langages dits «évolués».

II.3.5.3.EXEMPLE DE COMPILATION:

Le schéma ci-dessous donne un aperçu du travail effectué par un compilateur (le programme correspond à l'exemple du paragraphe II.2.4):


Exemple de Compilation


II.3.5.4.PHASES DE VIE D'UN PROGRAMME:

Le schéma suivant représente les étapes de la vie d'un programme, depuis sa création en langage évolué compilable jusqu'à son exécution:


Phases de vie d'un programme
  • PHASE 1-Développement: Le développeur crée un programme sous la forme de un ou plusieurs fichiers de texte en LANGAGE EVOLUE. Ce programme n'est pas directement exécutable par un processeur. Les fichiers obtenus sont appelés FICHIERS SOURCES du programme.




  • PHASE 2-Production: Chaque fichier source est d'abord traduit en LANGAGE INTERNE SYMBOLIQUE (ou LANGAGE D'ASSEMBLAGE) par des logiciels appelés COMPILATEURS. Un autre programme appelé EDITEUR DE LIENS se charge de réunir et lier entre eux les différents fichiers résultant de la compilation. Le résultat est assez proche du langage interne, à la seule différence que les adresses mémoires ne sont pas définies (on dit qu'elles sont TRANSLATABLES). Ce type de fichier est dit «exécutable».




  • PHASE 3-Execution: Au moment de l'exécution, le système d'exploitation détermine en fonction des disponibilités les zones de mémoire qu'il peut attribuer au programme. Il lance alors un logiciel appelé CHARGEUR qui remplace les adresses symboliques du fichier par des adresses numériques et implante le programme obtenu en mémoire. Le système d'exploitation peut alors gérer la vie du programme en mémoire (lancement, arrêt, mise en attente d'un événement ou d'une ressource, désallocation de la mémoire en fin d'utilisation).


REMARQUE:
Lorsque le système d'exploitation lance l'exécution d'un programme, il ne charge pas toujours la totalité de ce programme en mémoire: il peut n'en charger qu'une partie (dite résidente) qui assure l'enchaînement des traitements. Les parties supportant chaque traitement ne sont chargées que lorsque la partie résidente en fait la demande au système d'exploitation. La mémoire est désallouée dès que le programme est terminé. Ce type de traitement, qui permet de minimiser l'occupation mémoire des programmes, est souvent appliqué aux systèmes d'exploitation eux-mêmes, à cause de leur très fort volume: seul un NOYAU est chargé en résident permanent, les autres fonctions étant chargées à la demande.


II.3.6.PROCESSUS ET PARALLELISME:

II.3.6.1.NOTION DE PROCESSUS:

Nous avons vu plus haut que pour exécuter un programme, il faut d'abord en charger une copie (on dit une INSTANCE) en mémoire centrale. Le processeur peut alors exécuter les instructions qu'il contient. Une INSTANCE en cours d'exécution d'un programme donné constitue un PROCESSUS logiciel (ne pas confondre avec un PROCESSEUR, qui est le composant matériel qui exécute le PROCESSUS).


REMARQUE:
Le mot TACHE est souvent enployé à la place de PROCESSUS. Bien que ces deux notions ne soient pas totalement identiques, nous pouvons les confondre dans le cadre du présent cours.


II.3.6.2.NOTION DE THREAD:

Pour un processeur, exécuter un logiciel revient à parcourir une suite d'instructions de ce programme. Nous avons vu plus haut que l'ordre d'exécution des instruction n'est pas totalement déterminé par l'ordre d'écriture du programme, mais plutôt par la logique de celui-ci, car il existe des instructions de rupture conditionnelle de séquence. Cette suite, ce «fil d'instructions» contrôle») est désigné par le terme anglais THREAD (que l'on peut traduire par fil ou filin).
Les threads sont donc les «unités d'exécution» des logiciels. Pour s'exécuter, un processus doit comprendre au moins un thread (appelé thread principal). De plus, le code objet d'un processus peut être conçu de façon à pouvoir être exécuté sous la forme de plusieurs threads. Par exemple, un navigateur internet peut comprendre un thread qui traite les entrées-sorties sur la connexion internet et un autre thread qui s'occupe de l'interface avec l'utilisateur (clavier, souris, écran).


II.3.6.3.NOTION DE PARALLELISME:

L'exécution de deux ou plusieurs threads est qualifiée de PARALLELE lorsqu'un observateur a l'IMPRESSION que ceux-ci s'exécutent SIMULTANÉMENT.


II.3.6.4.EXECUTION EN PARALLELISME APPARENT:

A un instant donné, plusieurs programmes peuvent résider dans la mémoire centrale d'un ordinateur. Un processeur se conformant au modèle de VON NEUMAN ne peut en exécuter qu'un seul à la fois. Cependant, il est possible de partager le temps d'exécution du processeur entre plusieurs threads. Nous donnons ci-dessous deux des méthodes possibles:


UTILISATION DES PERIODES D'ATTENTE PASSIVE DES THREADS (MULTIPROGRAMMATION):
La plupart des programmes sont contraints, à certains stades de leur exécution, d'attendre la libération d'une ressource ou la survenue d'un événement conditionnant la poursuite de leur exécution.


EXEMPLES:
  • Un thread de programme ayant besoin de lire ou écrire sur un disque dur doit attendre que les têtes de lecture-écriture soient bien positionnées, ce qui peut demander quelques dizaines de millisecondes d'attente.
  • Un thread de dialogue homme-machine peut rester en attente d'une commande de l'utilisateur ou de la saisie d'une réponse à une question pendant un temps indéterminé.
  • Un thread recevant de la vidéo à afficher en « streaming » sur l'écran de l'ordinateur passe une grande partie du temps à attendre l'arrivée de messages sur la liaison internet.


En fait, la plupart des programmes interactifs (les navigateurs, par exemple), passent beaucoup plus de temps en attente (d'une commande, d'un message, de la libération d'un équipement, etc) qu'en exécution. Il est alors possible de mettre à profit ces périodes d'attente pour exécuter d'autres threads, et un observateur a alors l'impression que ces threads s'exécutent simultanément. Le schéma suivant illustre cette technique appelée MULTI-PROGRAMMATION:


Multiprogrammation
PROGRAMMATION EN TEMPS PARTAGE:
Cette autre technique consiste en un partage à parts égale du temps d'exécution du processeur entre les threads prèts à être exécutés: une certaine durée DT est allouée par roulement à chaque thread prèt, comme l'illustre le schema ci-dessous (comme DT est choisie faible par rapport à la perception humaine (par exemple, DT=100 ms), l'utilisateur a l'impression d'une exécution simultanée. Cette technique s'appelle «exécution en TEMPS PARTAGE» (ou TIME SHEARING en anglais):


Execution en temps partage.


REMARQUES:
  • La gestion de la multiprogrammation et du partage du temps d'exécution est effectuée par le système d'exploitation de l'ordinateur, que nous aborderons au chapitre IV.
  • Les deux techniques (multiprogrammation et temps partagé) sont employées simultanément. De ce fait, un thread en temps partagé qui tombe en attente avant la fin de sa durée Dt allouée perd immédiatement le processeur au profit d'un autre thread.


NOTION DE FLOT DE CONTRÔLE:
La suite réelle des instructions exécutées par le processeur est appelée FLOT (OU FLUX) DE CONTRÔLE. En mode multitâche, comme nous l'avons vu ci-dessus, ce flot de contrôle peut passer d'un thread à un autre au grès de l'arbitrage fait par le système d'exploitation. Executer un thread revient à lui attribuer le flot de contrôle d'un processeur (ne pas confondre la notion de flot de contrôle avec celle de thread, qui concerne la suite d'instruction exécutées par un processeur à l'intérieur d'un programme donné, en fonction de la logique de ce programme: le flot de contrôle est constitué de segments de threads, exécutés en fonction des rêgles de partage du temps d'exécution).


II.3.6.5.EXECUTION EN PARALLELISME REEL:

Pour que plusieurs threads puissent réellement s'exécuter en parallèle, il faut pouvoir disposer d'autant d'exécutants que de threads. De telles machines équipées de plusieurs processeurs indépendants sont appelées «SYSTEMES MULTIPROCESSEURS».




Retour accès cours Retour sommaire cours